package com.lin.server.ws;

import com.lin.entity.PlaneData;
import com.lin.entity.key.WsDataMapKey;
import com.lin.entity.key.WsTopicKey;
import com.lin.enums.ScheduleTask;
import com.lin.enums.SocketTopic;
import com.lin.mapper.PlaneDataMapper;
import com.lin.server.task.PlaneDataInTask;
import com.lin.utils.CommonUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.Session;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;

/**
 * websocket数据处理器
 */
@Component
@Slf4j
@Data
public class WsHandle {

    @Autowired
    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;

    @Autowired
    private WebSocketServer webSocketServer;

    @Autowired
    private WsDataHolder wsDataHolder;

    @Autowired
    private PlaneDataMapper planeDataMapper;


    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");




    /**
     * websocket 处理客户端的连接行为
     *
     * @param session 连接会话
     */
    public void handleOpen(Session session) {
        String topic = CommonUtils.getParameter(session.getQueryString(), "topic");

        if (SocketTopic.PLANE_DATA.getTopicName().equals(topic)) {

            PlaneDataInTask planeDataInTask = new PlaneDataInTask(wsDataHolder, planeDataMapper);
            this.createScheduleTask(ScheduleTask.PLANE_DATA_IN_TASK, planeDataInTask, ScheduleTask.PLANE_DATA_IN_TASK.getTaskName(), null);

        }
    }


    public void handleByteMessage(ByteBuffer message, String topic) {
        if (SocketTopic.PLANE_DATA.getTopicName().equals(topic)) {
            PlaneData planeData = CommonUtils.processBinaryPlaneData(message);
            wsDataHolder.getPlaneDataList().add(planeData);

        }
    }

    /**
     * 创建定时任务
     *
     * @param scheduleTask 任务枚举信息
     * @param task         线程任务
     * @param taskName
     */
    private void createScheduleTask(ScheduleTask scheduleTask, Runnable task, String taskName, Long userId) {
        if (wsDataHolder.getScheduleTask(new WsDataMapKey(taskName, userId)) == null) {
            log.info("用户{}，创建定时任务：{}", userId, taskName);
            ScheduledFuture<?> scheduledFuture = scheduledThreadPoolExecutor.scheduleAtFixedRate(
                    task,
                    0,
                    scheduleTask.getPeriod(),
                    scheduleTask.getUnit()
            );
            wsDataHolder.addTask(new WsDataMapKey(taskName, userId), scheduledFuture, task);
        }
    }

    /**
     * 停止定时任务
     *
     * @param taskName
     */
    public void stopScheduleTask(String taskName, Long userId) {
        log.info("用户{}，停止任务：{}", userId, taskName);
        ScheduledFuture<?> task = wsDataHolder.getScheduleTask(new WsDataMapKey(taskName, userId));
        if (task != null) task.cancel(false);
        wsDataHolder.removeTask(new WsDataMapKey(taskName, userId));
    }


    /**
     * websocket 处理客户端的断开连接行为
     *
     * @param topicKey
     */
    public void handleClose(WsTopicKey topicKey) {
        // 判断topic订阅用户不为0
        if (webSocketServer.getSessionOnlineCount(topicKey) != 0) return;

        String topic = topicKey.getTopic();
        if (SocketTopic.PLANE_DATA.getTopicName().equals(topic)) {
            // zh断开连接
            ((PlaneDataInTask) wsDataHolder.getThreadTask(new WsDataMapKey(ScheduleTask.PLANE_DATA_IN_TASK.getTaskName(), topicKey.getUserId()))).clearPlaneData();
            this.stopScheduleTask(ScheduleTask.PLANE_DATA_IN_TASK.getTaskName(), null);

        } else if (SocketTopic.PLANE.getTopicName().equals(topic)) {
            this.stopScheduleTask(ScheduleTask.GET_NEWEST_PLANE_TASK.getTaskName(), topicKey.getUserId());
//            this.stopScheduleTask(ScheduleTask.TRACE_PLANE_TASK.getTaskName(), topicKey.getUserId()); 追踪任务不清

        } else if (SocketTopic.TRACE_PLAYBACK.getTopicName().equals(topic)) {
            this.stopScheduleTask(ScheduleTask.TRACE_PLAYBACK_TASK.getTaskName(), topicKey.getUserId());
            wsDataHolder.getTracePlaybackCache().clear(); // 清空缓存的数据
        }

    }

    public void handleError(String topic) {
        if (topic != null && topic.equals(SocketTopic.PLANE_DATA.getTopicName())) {
            ((PlaneDataInTask) wsDataHolder.getThreadTask(new WsDataMapKey(ScheduleTask.PLANE_DATA_IN_TASK.getTaskName(), null))).clearPlaneData();
        }
    }

}
